﻿using System;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using DeepZoomPivotConstructor.ErrorAndLoggingInterfaces;
using DeepZoomPivotConstructor.VisualLib;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using RenderEngineInterfaces;
using UriRenderer;

namespace t_UriRenderer
{
    /// <summary>
    /// Specific tests checking on how the rendering of a URI that points to a html page goes.
    /// This requires some special stuff, actually, as we need to get rid of relative
    /// references.
    /// </summary>
    [TestClass]
    public class t_UriRenderHTML
    {
        [TestInitialize]
        public void InitForTest()
        {
            HttpAgentString = "Deeptalk library RenderUri Test";
            t_TestingLibrary.Utilities.MyClassInit();
            mylogger = new t_TestingLibrary.TestLogger();
            t_TestingLibrary.Utilities.AddPart(this);
            RenderingTempDir = null;
        }

        [Export(typeof(IErrorLogger))]
        private IErrorLogger mylogger;

        [Import]
        private IRenderEngine MyRender { get; set; }

        [Export("RenderingTempDir")]
#pragma warning disable 0414
        private DirectoryInfo RenderingTempDir;
#pragma warning restore 0414

        [Export("HttpAgentString")]
#pragma warning disable 0414
        private string HttpAgentString;
#pragma warning restore 0414

        [TestCleanup]
        public void ShutDownTest()
        {
            t_TestingLibrary.Utilities.MyClassDone();
        }

        [Export(typeof(IRenderItem))]
        [RenderInfo(typeof(FileInfo))]
        class RenderAFile : IRenderItem
        {
            public string ValidExt = ".pdf";
            public FileInfo FileRendered;

            public bool wasCalled = false;

            public System.Threading.Tasks.Task<Visual> Render(object what)
            {
                return Task<Visual>.Factory.StartNew(() =>
                {
                    wasCalled = true;
                    FileRendered = what as FileInfo;
                    Trace.WriteLine("Rendering " + FileRendered.ToString());
                    return new VisualBitmapImage(2.0, 3.0, 100, Color.Black);
                });
            }

            public RenderPluginPriority RenderPriority(object what)
            {
                FileInfo f = what as FileInfo;
                if (f.Extension == ValidExt)
                {
                    return RenderPluginPriority.RPPGeneric;
                }

                if (ValidExt == "")
                {
                    return RenderPluginPriority.RPPGeneric;
                }

                return RenderPluginPriority.RPPCantDoIt;
            }
        }

        [TestMethod]
        public void TestHTML()
        {
            Uri u = new Uri("http://www-d0.fnal.gov/");
            RenderEngineSingleHTML rh = new RenderEngineSingleHTML();
            t_TestingLibrary.Utilities.AddPart(rh);
            RenderUri uriR = new RenderUri();
            t_TestingLibrary.Utilities.Compose(uriR);

            var result = uriR.Render(u).Result;
            Assert.IsNotNull(result, "Expecting a future from that render!");
            Assert.AreEqual(1, result.SGNodeList.Count, "Expected one image as background there!");
            Assert.IsTrue(rh.wasCalled, "Rendering for the html was never called!");
        }

        [TestMethod]
        public void TestHTMLRelativeURLReplacement()
        {
            CheckRelativeURLReplacement("http://www-d0.fnal.gov/");
        }

        [TestMethod]
        public void TestHTMRelativeURLReplacement()
        {
            CheckRelativeURLReplacement("http://d0.phys.washington.edu/~gwatts/research/default.htm");
        }

        [TestMethod]
        public void TestSHTMLRelativeURLReplacement()
        {
            CheckRelativeURLReplacement("http://www.er.doe.gov/hep/agendas/index.shtml");
        }

        [TestMethod]
        public void TestSHTMLRelativeURLReplacement2()
        {
            CheckRelativeURLReplacement("http://www.er.doe.gov/hep/agendas/HEPAPAgendaMarch2010.shtml");
        }

        [TestMethod]
        [DeploymentItem("UrlRelative.html")]
        public void TestUrlRelativeReplacement()
        {
            FileInfo f = new FileInfo("UrlRelative.html");
            Assert.IsTrue(f.Exists, "Test file doesn't exist! Bad!");
            RenderUri r = new RenderUri();
            FileInfo result = r.UpdateRelativeLines(f, "http://www.nytimes.com");
            using (var reader = result.OpenText())
            {
                string html = reader.ReadToEnd();
                Assert.IsTrue(html.Contains("http://www.nytimes.com/junk.html"), "Missing the properly formatted link");
            }
        }

        [TestMethod]
        [DeploymentItem("UrlRelative.html")]
        public void TestUrlRelativeReplacement2()
        {
            FileInfo f = new FileInfo("UrlRelative.html");
            Assert.IsTrue(f.Exists, "Test file doesn't exist! Bad!");
            RenderUri r = new RenderUri();
            FileInfo result = r.UpdateRelativeLines(f, "http://www.nytimes.com/subd/");
            using (var reader = result.OpenText())
            {
                string html = reader.ReadToEnd();
                Assert.IsTrue(html.Contains("http://www.nytimes.com/subd/junk.html"), "Missing the properly formatted link");
            }
        }

        [TestMethod]
        [DeploymentItem("SiteRelative.html")]
        public void TestSiteRelativeReplacement()
        {
            FileInfo f = new FileInfo("SiteRelative.html");
            Assert.IsTrue(f.Exists, "Test file doesn't exist! Bad!");
            RenderUri r = new RenderUri();
            FileInfo result = r.UpdateRelativeLines(f, "http://www.nytimes.com/subd");
            using (var reader = result.OpenText())
            {
                string html = reader.ReadToEnd();
                Assert.IsTrue(html.Contains("http://www.nytimes.com/junk.html"), "Missing the properly formatted link");
            }
        }

        private void CheckRelativeURLReplacement(string uri)
        {
            ///
            /// If we download a html page to a file we need to fix up relative URLS in the text
            /// or we'll not be able to access them later. This is painful! :-)
            /// 
            /// We know the DZERO home page contains some relative hrefs. So we need to make sure
            /// the sub-renders that are called are a-ok.
            /// 

            Uri u = new Uri(uri);
            t_TestingLibrary.Utilities.AddPart(new RenderEngineSingleHTML());
            RenderUri uRender = new RenderUri();
            t_TestingLibrary.Utilities.Compose(uRender);

            var result = uRender.Render(u).Result;
            Assert.IsNotNull(result, "Expecting a future from that render!");
        }

        [Export(typeof(IRenderEngine))]
        class RenderEngineSingleHTML : IRenderEngine
        {
            public bool wasCalled = false;
            public Task<Visual> RenderToFuture(object what, Type[] disallowRenderPlugins = null, bool forceAsComposableUnit = false, bool asComposableUnitIfNoneWithin = false)
            {
                return Task<Visual>.Factory.StartNew(() => RenderObjectAndCheck(what));
            }

            private Visual RenderObjectAndCheck(object what)
            {
                FileInfo f = what as FileInfo;
                wasCalled = true;
                using (var reader = f.OpenText())
                {
                    string totalFile = reader.ReadToEnd();
                    Regex hrefer = new Regex("href=\"([^\"]+)\"");
                    var m = hrefer.Match(totalFile);
                    int matchCount = 0;
                    while (m.Success)
                    {
                        matchCount++;
                        string link = m.Groups[1].Value;
                        Trace.WriteLine("Converted link: " + link);
                        Assert.IsTrue(link.StartsWith("http://") || link.StartsWith("https") || link.StartsWith("mailto:"), "Line does not start with http - looks relative: " + link);
                        Assert.IsFalse(link.Contains("mailto:") && !link.StartsWith("mailto:"), "We seem to have converted a mail-to link: " + link);
                        m = m.NextMatch();
                    }
                    Assert.IsTrue(matchCount > 0, "Expecting at least one href in the resulting html!");
                }
                return new VisualBitmapImage(2.0, 3.0, 100, Color.Black);
            }

            public Visual Render(object what, Type[] disallowRenderPlugins = null, bool forceAsComposableUnit = false, bool asComposableUnitIfNoneWithin = false)
            {
                return RenderToFuture(what, disallowRenderPlugins, forceAsComposableUnit).Result;
            }
        }
    }
}
